package com.benchmark.springboot.controller;

import com.benchmark.springboot.concurrent.MyCallable;
import com.benchmark.springboot.model.User;
import com.benchmark.springboot.service.AsyncService;
import com.power.common.model.CommonResult;
import com.power.common.util.CollectionUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;

/**
 * 异步Controller
 *
 * @author yu 2019/2/16.
 */
@RestController
public class AsyncController {

    private static final Logger LOGGER = LoggerFactory.getLogger(AsyncController.class);


    @Resource
    AsyncService asyncService;

    @Resource
    ThreadPoolTaskExecutor mvcTaskExecutor;

    /**
     * 测试callable
     *
     * @return
     */
    @GetMapping(value = "/testCallable")
    public Callable<CommonResult<String>> testCallable() {
        return () -> {
            long sleep = ThreadLocalRandom.current().nextInt(1000);
            LOGGER.info("睡眠时间：{}", sleep);
            Thread.sleep(sleep);
            return CommonResult.ok().setResult("Hello World !!");
        };
    }

    /**
     * 异步无返回
     *
     * @return
     */
    @GetMapping("asyncNoReturn")
    public CommonResult<String> testAsyncNoReturn() {
        long start = System.currentTimeMillis();
        asyncService.doNoReturn();
        String str = String.format("任务执行成功,耗时{%s}", System.currentTimeMillis() - start);
        return CommonResult.ok().setResult(str);
    }

    /**
     * 测试异步返回
     * @apiNote 并发将多个处理结果合并返回
     * @return
     * @throws ExecutionException
     * @throws InterruptedException
     */
    @GetMapping("asyncReturn")
    public CommonResult<String> testAsyncReturn() throws ExecutionException, InterruptedException {
        long start = System.currentTimeMillis();

        List<Future<String>> futures = new ArrayList<>();
        for (int i = 0; i < 8; i++) {
            Future<String> future = asyncService.doReturn(i);
            futures.add(future);
        }
        List<String> response = new ArrayList<>();
        for (Future<String> future : futures) {
            //future可以在get时设置超时
            String string = future.get();
            response.add(string);
        }
        LOGGER.info("任务执行成功,耗时{}毫秒", System.currentTimeMillis() - start);
        return CommonResult.ok().setResult(response);
    }

    /**
     * CountDownLatch等待
     * @apiNote 测试CountDownLatch异步执行等待
     * @return
     * @throws ExecutionException
     * @throws InterruptedException
     */
    @GetMapping("asyncCountDownLatchWait")
    public CommonResult<String> testAsyncCountDownLatch() throws ExecutionException, InterruptedException {
        long start = System.currentTimeMillis();
        CountDownLatch latch = new CountDownLatch(8);
        for (int i = 0; i < 8; i++) {
            String thread = String.valueOf(i);
            mvcTaskExecutor.submit(()->{
                asyncService.doAsync(thread);
                latch.countDown();
            });
        }
        // 等待所有执行完毕
        latch.await();
        LOGGER.info("任务执行成功,耗时{}毫秒", System.currentTimeMillis() - start);
        return CommonResult.ok();
    }


    /**
     * 异步同步数据
     *
     * @return
     */
    @GetMapping("asyncData")
    public CommonResult<String> asyncData() {
        long start = System.currentTimeMillis();
        List<User> users = new ArrayList<>(2000);
        for (int i = 0; i < 2000; i++) {
            User user = new User();
            user.setId(i);
            user.setName("name_" + i);
            users.add(user);
        }
        List<Future<String>> futureList = new ArrayList<>();
        //8个线程,每个线程大概225条
        List<List<User>> lists = CollectionUtil.partition(users, 200);
        int index = 0;
        for (List<User> list : lists) {
            futureList.add(asyncService.syncData(list, index));
            index++;
        }
        for (Future<String> future : futureList) {
            String str;
            if (null != future) {
                try {
                    str = future.get();
                    LOGGER.info("current thread id =" + Thread.currentThread().getName() + ",result=" + str);
                } catch (InterruptedException | ExecutionException e) {
                    LOGGER.info("线程运行异常！");
                }
            } else {
                LOGGER.info("线程运行异常！");
            }
        }
        LOGGER.info("任务执行成功,耗时{}毫秒", System.currentTimeMillis() - start);
        return CommonResult.ok();
    }

    /**
     * 调用callable异步执行
     *
     * @return
     */
    @GetMapping("callable")
    public CommonResult<String> callable() {
        mvcTaskExecutor.submit(new MyCallable());
        return CommonResult.ok();
    }
}
